package com.knowledge.plus.自定义注解.example3.aspect;

import com.knowledge.plus.自定义注解.example3.annotation.MyLog;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.Signature;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * @author PF.Tian
 * @since 2021/09/13
 */
@Aspect // 1.表明这是一个切面类
@Component
public class MyLogAspect {

    // 2. PointCut表示这是一个切点，@annotation表示这个切点切到一个注解上，后面带该注解的全类名
    // 切面最主要的就是切点，所有的故事都围绕切点发生
    // logPointCut()代表切点名称
    @Pointcut("@annotation(com.knowledge.plus.自定义注解.example3.annotation.MyLog)")
    public void logPointCut() {
    }

    // 3. 环绕通知，目标方法执行前后分别执行一些代码
    @Around("logPointCut()")
    public void logAround(ProceedingJoinPoint joinPoint) {
        // 获取方法名称
        String methodName = joinPoint.getSignature().getName();
        System.out.println("进入[" + methodName + "]方法");

        try {
            // 继续执行方法
            Object proceed = joinPoint.proceed();


            // 1. 获取入参
            Object[] param = joinPoint.getArgs();
            // 2. 参数名称
            {
                Signature signature = joinPoint.getSignature();
                if (signature instanceof MethodSignature) {
                    MethodSignature methodSignature = (MethodSignature) signature;
                    String[] properties = methodSignature.getParameterNames();
                }
            }
            // 3. 返回类型
            {
                Signature signature = joinPoint.getSignature();
                if (signature instanceof MethodSignature) {
                    MethodSignature methodSignature = (MethodSignature) signature;
                    // 被切的方法
                    Method method = methodSignature.getMethod();
                    // 返回类型
                    Class<?> methodReturnType = method.getReturnType();
                    // 实例化
                    Object o = methodReturnType.newInstance();
                }
            }
            // 4. 全限定类名
            {
                Signature signature = joinPoint.getSignature();
                String declaringTypeName = signature.getDeclaringTypeName();
            }
            // 5. 方法名
            {
                Signature signature = joinPoint.getSignature();
                String name = signature.getName();
            }
            // 6. 注解
            {
                Class<?> targetCls = joinPoint.getTarget().getClass();
                MethodSignature ms = (MethodSignature) joinPoint.getSignature();
                Method targetMethod = targetCls.getDeclaredMethod(ms.getName(), ms.getParameterTypes());
                MyLog annotation = targetMethod.getAnnotation(MyLog.class);
                boolean required = annotation.required();
            }

            // 获取 request response
            {
                HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
                HttpServletResponse response=((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getResponse();
            }

        } catch (Throwable throwable) {
            throwable.printStackTrace();
        } finally {

        }
        System.out.println(methodName + "方法执行结束");

    }

}
